import random
import json
import time
import psycopg2
import os
import secrets
from dotenv import load_dotenv
from psycopg2.extras import RealDictCursor

# 尝试不同的导入方式，以便支持不同的运行方式
try:
    # 当作为模块导入时
    from backend.config import DB_CONFIG, DEFAULT_MAX_CARDS_LIMIT, DEFAULT_DECKS, LOW_CARDS_THRESHOLD, BET_OPTIONS, DEFAULT_BET_AMOUNTS
    from backend.models import BetStrategyTable
except ImportError:
    # 当直接运行时
    from config import DB_CONFIG, DEFAULT_MAX_CARDS_LIMIT, DEFAULT_DECKS, LOW_CARDS_THRESHOLD, BET_OPTIONS, DEFAULT_BET_AMOUNTS
    from models import BetStrategyTable


def get_timestamp():
    """获取当前时间戳"""
    return time.strftime('%Y-%m-%d %H:%M:%S')

def create_deck(deck_num=8):
    """创建指定数量的牌组"""
    ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
    suits = ['♠', '♥', '♣', '♦']
    deck = []
    for _ in range(deck_num):
        for suit in suits:
            for rank in ranks:
                # 计算牌面值
                if rank in ['10', 'J', 'Q', 'K']:
                    value = 0
                elif rank == 'A':
                    value = 1
                else:
                    value = int(rank)
                deck.append((suit+rank, value))
    return deck

def shuffle_new_deck(deck_num=8, shuffle_times=7, fixed_seed=None):
    """
    生成并洗牌
    
    参数:
    deck_num: 使用的牌组数量
    shuffle_times: 洗牌次数，推荐7次以上以达到充分随机
    fixed_seed: 指定随机种子，用于重现相同的洗牌结果
    
    返回:
    deck: 洗好的牌组
    deck_seed: 随机种子，用于验证
    """
    # 使用指定种子或生成新的随机种子
    if fixed_seed is not None:
        deck_seed = fixed_seed
    else:
        deck_seed = secrets.randbelow(10000000)
    
    # 设置随机种子
    random.seed(deck_seed)
    
    # 创建新牌组
    deck = create_deck(deck_num)
    
    # 进行多次洗牌以确保充分随机
    for _ in range(shuffle_times):
        random.shuffle(deck)
        
    # 恢复随机种子以避免影响其他随机过程
    random.seed(None)
    
    return deck, deck_seed

def calculate_points(hand):
    """计算手牌点数"""
    if not hand:
        return 0
    total = sum(card[1] for card in hand)
    return total % 10

def should_player_draw_third(player_hand):
    """判断闲家是否需要补牌"""
    player_points = calculate_points(player_hand)
    # 闲家点数为0-5时补牌
    return len(player_hand) == 2 and player_points <= 5

def should_banker_draw_third(banker_hand, player_third_value=None):
    """判断庄家是否需要补牌"""
    banker_points = calculate_points(banker_hand)
    
    # 如果闲家没有补牌
    if player_third_value is None:
        # 庄家点数0-5补牌
        return banker_points <= 5
    
    # 闲家补了牌，庄家按照规则补牌
    if banker_points <= 2:
        return True  # 庄0,1,2点，无条件补牌
    elif banker_points == 3:
        return player_third_value != 8  # 庄3点，闲家补的牌不为8时补牌
    elif banker_points == 4:
        return player_third_value in [2, 3, 4, 5, 6, 7]  # 庄4点，闲家补的牌为2-7时补牌
    elif banker_points == 5:
        return player_third_value in [4, 5, 6, 7]  # 庄5点，闲家补的牌为4-7时补牌
    elif banker_points == 6:
        return player_third_value in [6, 7]  # 庄6点，闲家补的牌为6-7时补牌
    return False  # 庄7,8,9点不补牌

def determine_result(player_hand, banker_hand):
    """判断游戏结果"""
    player_score = calculate_points(player_hand)
    banker_score = calculate_points(banker_hand)
    
    if player_score > banker_score:
        return 'player'
    elif banker_score > player_score:
        return 'banker'
    else:
        return 'tie'

def calculate_payout(bet_choice, bet_amount, result, banker_score):
    """计算赔付金额（免佣百家乐规则）"""
    # 和局特殊处理：如果结果是和局，且玩家押注的是庄或闲，返还本金（不输不赢）
    if result == 'tie' and bet_choice != 'tie':
        return 0  # 返还本金，净收益为0
        
    if bet_choice != result:  # 未中奖
        return -bet_amount
        
    # 已中奖，计算赔付
    if bet_choice == 'banker':
        if banker_score == 6:  # 庄6点赢，赔率为1:0.5
            return int(bet_amount * 0.5)
        else:  # 庄其他点数赔率为1:1
            return bet_amount
    elif bet_choice == 'player':  # 闲赔率为1:1
        return bet_amount
    else:  # tie - 和赔率为1:8
        return bet_amount * 8

def play_single_round(deck, bet_choice=None, bet_amount=0, cards_dealt_count=0, main_choice=None):
    """模拟单局游戏，返回结果和更新后的牌堆"""
    # 检查牌堆是否足够
    if len(deck) < 6:  # 至少需要6张牌（双方各3张）
        return {
            'error': 'Not enough cards',
            'deck': deck,
            'cards_dealt_count': cards_dealt_count
        }
    
    # 发初始两张牌
    player_hand = [deck.pop() for _ in range(2)]
    banker_hand = [deck.pop() for _ in range(2)]
    cards_dealt_count += 4
    
    # 检查天牌 (Natural 8/9)
    player_points = calculate_points(player_hand)
    banker_points = calculate_points(banker_hand)
    
    if player_points >= 8 or banker_points >= 8:
        # 天牌不补牌
        pass
    else:
        # 闲家补牌规则
        if should_player_draw_third(player_hand):
            if deck:
                player_hand.append(deck.pop())
                cards_dealt_count += 1
                # 获取闲家第三张牌的点数，用于决定庄家是否补牌
                player_third_value = player_hand[2][1]
            else:
                return {
                    'error': 'Not enough cards for player third card',
                    'deck': deck,
                    'cards_dealt_count': cards_dealt_count
                }
        else:
            player_third_value = None
        
        # 庄家补牌规则
        if should_banker_draw_third(banker_hand, player_third_value):
            if deck:
                banker_hand.append(deck.pop())
                cards_dealt_count += 1
            else:
                return {
                    'error': 'Not enough cards for banker third card',
                    'deck': deck,
                    'cards_dealt_count': cards_dealt_count
                }
    
    # 确定结果
    result = determine_result(player_hand, banker_hand)
    
    # 计算最终点数
    player_points = calculate_points(player_hand)
    banker_points = calculate_points(banker_hand)
    
    # 计算赔付金额
    payout = 0
    win = False
    
    if bet_choice and bet_amount > 0:
        # 如果结果是和局，且下注的是庄或闲，设置特殊的输赢状态（不输不赢）
        if result == 'tie' and bet_choice != 'tie':
            win = 2  # 特殊状态：和局退回本金
        else:
            win = (bet_choice == result)  # 正常判断输赢
        payout = calculate_payout(bet_choice, bet_amount, result, banker_points)
    
    # 返回完整游戏结果
    return {
        'player_hand': player_hand,
        'banker_hand': banker_hand,
        'player_points': player_points,
        'banker_points': banker_points,
        'result': result,
        'bet_choice': bet_choice,
        'bet_amount': bet_amount,
        'win': win,
        'payout': payout,
        'deck': deck,
        'cards_dealt_count': cards_dealt_count,
        'main_choice': main_choice
    }

def save_round_to_db(game_result, round_id=None, strategy_note=None, simulation_id=None):
    """保存单局游戏结果到数据库"""
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor()
        
        player_hand_json = json.dumps([card[0] for card in game_result['player_hand']], ensure_ascii=False)
        banker_hand_json = json.dumps([card[0] for card in game_result['banker_hand']], ensure_ascii=False)
        
        # 处理游戏结果的win字段
        # win=True表示赢, win=False表示输, win=2表示和局情况下庄闲下注返还本金
        win_value = game_result.get('win', False)
        win_or_lose = 2 if win_value == 2 else (1 if win_value else 0)
        
        # 处理bet_choice，确保None值转为空字符串
        bet_choice = game_result.get('bet_choice', '')
        if bet_choice is None:
            bet_choice = ''
        
        # 如果是模拟，记录额外信息
        if simulation_id:
            cursor.execute('''
                INSERT INTO simulation_rounds (
                    timestamp, simulation_id, round_id, bet_choice, bet_amount, result, 
                    win_or_lose, payout, player_hand, banker_hand, player_points, 
                    banker_points, strategy_note, main_choice
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                RETURNING id
            ''', (
                get_timestamp(),
                simulation_id,
                round_id,
                bet_choice,
                game_result.get('bet_amount', 0),
                game_result['result'],
                win_or_lose,
                game_result.get('payout', 0),
                player_hand_json,
                banker_hand_json,
                game_result['player_points'],
                game_result['banker_points'],
                strategy_note,
                game_result.get('main_choice', '')
            ))
        else:
            # 常规游戏记录
            cursor.execute('''
                INSERT INTO rounds (
                    timestamp, bet_choice, bet_amount, result, win_or_lose, payout,
                    player_hand, banker_hand, player_points, banker_points, main_choice
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                RETURNING id
            ''', (
                get_timestamp(),
                bet_choice,
                game_result.get('bet_amount', 0),
                game_result['result'],
                win_or_lose,
                game_result.get('payout', 0),
                player_hand_json,
                banker_hand_json,
                game_result['player_points'],
                game_result['banker_points'],
                game_result.get('main_choice', '')
            ))
        
        # 获取插入的记录ID
        row_id = cursor.fetchone()[0]
        conn.commit()
        return row_id
    except Exception as e:
        print(f"Database error: {str(e)}")
        if conn:
            conn.rollback()
        return None
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

def init_database():
    """初始化数据库表结构"""
    conn = None
    try:
        # 连接数据库
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor()
        
        # 创建轮次表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS rounds (
                id SERIAL PRIMARY KEY,
                timestamp TEXT,
                bet_choice TEXT,
                bet_amount INTEGER,
                result TEXT,
                win_or_lose INTEGER,
                payout INTEGER,
                player_hand TEXT,
                banker_hand TEXT,
                player_points INTEGER,
                banker_points INTEGER,
                main_choice TEXT
            )
        ''')
        
        # 创建模拟记录表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS simulations (
                id SERIAL PRIMARY KEY,
                timestamp TEXT,
                strategy_name TEXT,
                total_rounds INTEGER,
                win_rounds INTEGER,
                lose_rounds INTEGER,
                net_profit REAL,
                deck_seed TEXT,
                parameters TEXT,
                main_choice TEXT
            )
        ''')
        
        # 创建模拟轮次表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS simulation_rounds (
                id SERIAL PRIMARY KEY,
                timestamp TEXT,
                simulation_id INTEGER REFERENCES simulations(id),
                round_id INTEGER,
                bet_choice TEXT,
                bet_amount INTEGER,
                result TEXT,
                win_or_lose INTEGER,
                payout INTEGER,
                player_hand TEXT,
                banker_hand TEXT,
                player_points INTEGER,
                banker_points INTEGER,
                strategy_note TEXT,
                main_choice TEXT
            )
        ''')
        
        # 创建牌组表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS decks (
                id SERIAL PRIMARY KEY,
                timestamp TEXT,
                simulation_id INTEGER REFERENCES simulations(id),
                deck_data TEXT,
                original_size INTEGER,
                deck_seed INTEGER
            )
        ''')
        
        # 创建下注策略表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS bet_strategies (
                id SERIAL PRIMARY KEY,
                name TEXT UNIQUE,
                description TEXT,
                level1 TEXT,
                level2 TEXT,
                level3 TEXT,
                created_at TEXT,
                updated_at TEXT,
                is_default BOOLEAN DEFAULT FALSE
            )
        ''')
        
        # 检查是否已有默认策略
        cursor.execute("SELECT COUNT(*) FROM bet_strategies WHERE is_default = TRUE")
        default_count = cursor.fetchone()[0]
        
        # 如果没有默认策略，插入默认策略
        if default_count == 0:
            from config import BET_AMOUNT_TABLES
            default_strategy = BET_AMOUNT_TABLES['default']
            
            cursor.execute('''
                INSERT INTO bet_strategies (
                    name, description, level1, level2, level3, created_at, updated_at, is_default
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
            ''', (
                'default',
                '默认三级注码策略',
                json.dumps(default_strategy['level1']),
                json.dumps(default_strategy['level2']),
                json.dumps(default_strategy['level3']),
                get_timestamp(),
                get_timestamp(),
                True
            ))
        
        # 提交事务
        conn.commit()
        print("数据库表结构初始化成功!")
        
    except Exception as e:
        print(f"数据库初始化错误: {str(e)}")
        if conn:
            conn.rollback()
    
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

def get_history(limit=10):
    """获取最近的游戏历史记录"""
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor(cursor_factory=RealDictCursor)
        
        cursor.execute('''
            SELECT * FROM rounds 
            ORDER BY id DESC 
            LIMIT %s
        ''', (limit,))
        
        history = cursor.fetchall()
        
        # 解析JSON字段
        for row in history:
            if row['player_hand']:
                row['player_hand'] = json.loads(row['player_hand'])
            if row['banker_hand']:
                row['banker_hand'] = json.loads(row['banker_hand'])
                
        return history
    except Exception as e:
        print(f"Error fetching history: {str(e)}")
        return []
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

def clear_history():
    """清空游戏历史记录"""
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor()
        
        cursor.execute('DELETE FROM rounds')
        conn.commit()
        return True
    except Exception as e:
        print(f"Error clearing history: {str(e)}")
        if conn:
            conn.rollback()
        return False
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

def clear_all_simulations():
    """清空所有模拟记录及相关的轮次记录"""
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor()
        
        # 正确的删除顺序：先删除引用表，再删除被引用表
        # 1. 先删除所有模拟轮次记录
        cursor.execute('DELETE FROM simulation_rounds')
        
        # 2. 删除decks表中引用simulation_id的记录
        cursor.execute('DELETE FROM decks WHERE simulation_id IS NOT NULL')
        
        # 3. 最后删除模拟记录
        cursor.execute('DELETE FROM simulations')
        
        conn.commit()
        cursor.close()
        conn.close()
        
        return True
    except Exception as e:
        print(f"Error in clear_all_simulations: {str(e)}")
        if conn:
            conn.rollback()
        return False

def clear_simulation(simulation_id):
    """清空特定ID的模拟记录及其相关轮次"""
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor()
        
        # 正确的删除顺序：先删除引用表，再删除被引用表
        # 1. 先删除相关的模拟轮次记录
        cursor.execute('DELETE FROM simulation_rounds WHERE simulation_id = %s', (simulation_id,))
        
        # 2. 删除decks表中引用此simulation_id的记录
        cursor.execute('DELETE FROM decks WHERE simulation_id = %s', (simulation_id,))
        
        # 3. 最后删除模拟记录
        cursor.execute('DELETE FROM simulations WHERE id = %s', (simulation_id,))
        
        affected_rows = cursor.rowcount
        conn.commit()
        cursor.close()
        conn.close()
        
        return affected_rows > 0
    except Exception as e:
        print(f"Error in clear_simulation: {str(e)}")
        if conn:
            conn.rollback()
        return False

# 策略模拟相关功能

def determine_bet_by_strategy(history, main_choice=None):
    """根据"三反四看五跟"策略确定下注方向
    
    Args:
        history: 之前几局的结果列表，最新的在最后
        main_choice: 主打方向('player'或'banker')
    
    Returns:
        下注选择('player', 'banker', None)，None表示不下注
    """
    if not history:
        return None
    
    # 如果还没有确定主打方向，使用第一局的结果
    if not main_choice:
        for result in history:
            if result != 'tie':  # 和局不算
                main_choice = result
                break
    
    if not main_choice:  # 如果全是和局，不下注
        return None
    
    # 获取最近的结果（不包括和局）
    recent_results = []
    for result in reversed(history):
        if result != 'tie':
            recent_results.append(result)
        if len(recent_results) >= 5:
            break
    
    # 检查是否有连续的相同结果
    # 注意：recent_results中是按照时间倒序排列的，最新的在最前面
    
    # 如果没有足够的历史记录，默认跟主打
    if len(recent_results) == 0:
        return main_choice
        
    # 获取最新的非和局结果
    latest_result = recent_results[0]
    
    # 计算连续出现的相同结果数量
    streak_count = 0
    for result in recent_results:
        if result == latest_result:
            streak_count += 1
        else:
            break
    
    # 应用"三反四看五跟"策略
    if streak_count >= 5:  # 五连以上跟
        return latest_result
    elif streak_count == 4:  # 四连看，不下注
        return None
    elif streak_count == 3:  # 三连反
        return 'player' if latest_result == 'banker' else 'banker'
    else:  # 一连或二连，跟主打
        return main_choice

def get_bet_strategy(name=None):
    """
    从数据库获取下注策略
    
    参数:
    name: 策略名称，如果为None则获取默认策略
    
    返回:
    策略字典，包含level1, level2, level3三个注码列表
    """
    from models import BetStrategy
    
    try:
        # 如果指定了策略名称，获取该策略
        if name:
            strategy = BetStrategy.get_by_name(name)
        else:
            # 否则获取默认策略
            strategy = BetStrategy.get_default()
        
        if strategy:
            return {
                'level1': strategy.level1,
                'level2': strategy.level2,
                'level3': strategy.level3
            }
        else:
            print("获取下注策略失败")
            return None
    except Exception as e:
        print(f"获取下注策略错误: {str(e)}")
        return None

def save_bet_strategy(strategy):
    """
    保存下注策略到数据库
    
    参数:
    strategy: 包含策略信息的字典，格式如下：
    {
        'name': 策略名称,
        'description': 策略描述,
        'level1': 第一级注码列表,
        'level2': 第二级注码列表,
        'level3': 第三级注码列表,
        'is_default': 是否为默认策略 (可选)
    }
    
    返回:
    成功返回True，失败返回False
    """
    from models import BetStrategy
    
    try:
        # 检查必要的字段
        required_fields = ['name', 'level1', 'level2', 'level3']
        for field in required_fields:
            if field not in strategy:
                print(f"保存策略错误: 缺少必要字段 '{field}'")
                return False
        
        # 创建策略对象
        bet_strategy = BetStrategy(
            name=strategy['name'],
            description=strategy.get('description', ''),
            level1=strategy['level1'],
            level2=strategy['level2'],
            level3=strategy['level3'],
            is_default=strategy.get('is_default', False)
        )
        
        # 检查是否为更新操作
        if 'id' in strategy and strategy['id']:
            bet_strategy.id = strategy['id']
            
            # 检查是否存在
            existing = BetStrategy.get_by_id(bet_strategy.id)
            if not existing:
                print(f"更新策略错误: ID为{bet_strategy.id}的策略不存在")
                return False
        
        # 保存到数据库
        success = bet_strategy.save()
        
        if success:
            return True
        else:
            print("保存策略失败")
            return False
            
    except Exception as e:
        print(f"保存下注策略错误: {str(e)}")
        return False

def get_bet_strategy_table(id=None):
    """
    从数据库获取下注策略表
    
    参数:
    id: 策略表ID，如果为None则获取默认策略表
    
    返回:
    策略表字典，包含table_data列表
    """
    from models import BetStrategyTable
    
    try:
        # 如果指定了策略表名称，获取该策略表
        if id:
            strategy_table = BetStrategyTable.get_by_id(id)
        else:
            # 否则获取默认策略表
            strategy_table = BetStrategyTable.get_default()
        
        if strategy_table:
            return {
                'strategy_content': strategy_table.strategy_content,
                'name': strategy_table.name,
                'description': strategy_table.description
            }
        else:
            print("获取下注策略表失败")
            return None
    except Exception as e:
        print(f"获取下注策略表错误: {str(e)}")
        return None

def save_bet_strategy_table(strategy_table_data):
    """
    保存下注策略表到数据库
    
    参数:
    strategy_table_data: 包含策略表信息的字典，格式如下：
    {
        'name': 策略表名称,
        'description': 策略表描述,
        'strategy_content': 策略内容文本，
        'is_default': 是否为默认策略表 (可选)
    }
    
    返回:
    成功返回保存的策略表ID，失败返回None
    """
    from models import BetStrategyTable
    
    try:
        # 检查必要的字段
        required_fields = ['name', 'strategy_content']
        for field in required_fields:
            if field not in strategy_table_data:
                print(f"保存策略表错误: 缺少必要字段 '{field}'")
                return None
        
        # 创建策略表对象
        strategy_table = BetStrategyTable(
            name=strategy_table_data['name'],
            description=strategy_table_data.get('description', ''),
            strategy_content=strategy_table_data['strategy_content'],
            is_default=strategy_table_data.get('is_default', False)
        )
        
        # 检查是否为更新操作
        if 'id' in strategy_table_data and strategy_table_data['id']:
            strategy_table.id = strategy_table_data['id']
            
            # 检查是否存在
            existing = BetStrategyTable.get_by_id(strategy_table.id)
            if not existing:
                print(f"更新策略表错误: ID为{strategy_table.id}的策略表不存在")
                return None
        
        # 保存到数据库
        success = strategy_table.save()
        
        if success:
            return strategy_table.id
        else:
            print("保存策略表失败")
            return None
            
    except Exception as e:
        print(f"保存下注策略表错误: {str(e)}")
        return None

def determine_bet_amount_by_strategy(previous_results, strategy_table=None):
    """根据输赢记录确定下注金额
    previous_results的格式：
        ['+1000', '-1000', '+1100','0',...],0表示和局或者没下注，+1000表示赢1000，-1000表示输1000
    
    策略表strategy_table格式：[{conditions: bet_amount}, {conditions: bet_amount}, ...]
        三种情况:
        1. {'-1000': 1100} 表示如果上一局输1000，则下注1100
        2. {'+1000/+1100/+1300/+1700': 1100} 表示如果上一局赢1000或赢1100或赢1300或赢1700，则下注1100
        3. {'+2000,+2000,+2000': 1100} 表示最近三局都赢了2000，则下注1100
    
    Args:
        previous_results: 之前几局的输赢结果列表
        strategy_table: 策略表，如果为None则使用数据库中的默认策略表
    
    Returns:
        下一局的下注金额
    """        
    print(f"previous_results: {previous_results}")
    print(f"strategy_table: {strategy_table}")
    
    base_amount = 1000
    # 如果没有历史记录，从最小的1000开始
    if not previous_results:
        return base_amount
    
    # 如果previous_results中只有"0"，则返回base_amount
    if all(result == "0" for result in previous_results):
        return base_amount

    # 把previous_results最后的4个非"0"的记录按顺序合并为一个字符串,例如："+"1000","-1000","+1100","+1300",不足4个时，按实际数量合并
    # 从后往前找，找到4个非"0"的记录
    last_4_results = []
    for result in reversed(previous_results):
        if result != "0":
            last_4_results.append(result)
        if len(last_4_results) == 4:
            print(f"last_4_results: {last_4_results}")
            break
    # 把last_4_results按从后往前的顺序合并为一个字符串,例如："+"1000","-1000","+1100","+1300",不足4个时，按实际数量合并
    str_last_4_results = ""
    for result in reversed(last_4_results):
        str_last_4_results += "," + result
    
    print(f"str_last_4_results: {str_last_4_results}")
    # 获取最近一次的输赢记录
    last_result = last_4_results[0]
    
    # 找到有效记录后，根据策略表和previous_results之间的匹配关系，确定下注金额
    for rule in strategy_table:
        # 解析规则 - parse_strategy_text返回的是[{条件字符串: 下注金额}, ...]格式
        # 例如：rule={'+1000': 1000}
        condition = list(rule.keys())[0]  # 获取字典的第一个键
        bet_amount = rule[condition]      # 获取对应的值
        
        if not last_4_results:
            # 如果没有有效历史记录，返回默认值
            return base_amount
        
        # 获取最近一次的输赢记录
        last_result = last_4_results[0]
        
        result = bet_amount
        
        # 检查是否为连续条件匹配（使用,分隔）
        if ',' in condition:
            # str_last_4_results: , +3000, +3000, +3000, -2000
            # 连续条件匹配 - condition: +3000, +3000, +3000, bet_amount: 2000 这种情况有问题，应该是算作-2000:2200
            # 应该是从后往前截取和condition一样长度的字符串，然后比较是否相等
            # 从后往前截取和condition一样长度的字符串
            condition_len = len(condition)            
            last_condition_str = str_last_4_results[-condition_len:]
            if last_condition_str == condition:
                print(f"连续条件匹配 - condition: {condition}, bet_amount: {bet_amount}")
                result = bet_amount
                return result
        
        # 检查是否为简单匹配
        if last_result == condition:
            # 上一局输赢结果匹配上了条件，直接返回
            print(f"简单匹配 - condition: {condition}, bet_amount: {bet_amount}")
            result = bet_amount
            return result

        # 检查是否为多条件"或"匹配（使用/分隔）
        if '/' in condition:
            or_conditions = condition.split('/')
            if last_result in or_conditions:
                print(f"或条件匹配 - condition: {condition}, bet_amount: {bet_amount}")
                return bet_amount
                
        
    
    # 如果找不到匹配的记录，则返回base_amount
    return base_amount
    

def save_deck_to_db(original_deck, deck_seed, simulation_id=None):
    """
    保存牌组初始状态到数据库，便于后续验证
    
    参数:
    original_deck: 初始牌组
    deck_seed: 随机种子
    simulation_id: 关联的模拟ID
    """
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor()
        
        # 将牌组转为JSON保存
        deck_data_json = json.dumps([card[0] for card in original_deck], ensure_ascii=False)
        
        cursor.execute('''
            INSERT INTO decks (
                timestamp, simulation_id, deck_data, original_size, deck_seed
            ) VALUES (%s, %s, %s, %s, %s)
            RETURNING id
        ''', (
            get_timestamp(),
            simulation_id,
            deck_data_json,
            len(original_deck),
            deck_seed
        ))
        
        result = cursor.fetchone()
        conn.commit()
        cursor.close()
        conn.close()
        
        if result:
            return result[0]
        return None
        
    except Exception as e:
        print(f"保存牌组记录错误: {str(e)}")
        return None

def run_simulation(strategy_name, deck_seed=None, max_rounds=1000, parameters=None):
    """
    运行策略模拟
    {"strategy_name":"三反四看五跟测试","max_rounds":1000,"deck_seed":null,"parameters":{"observation_rounds":6,"strategy_table_id":2}}
    参数:
    strategy_name: 策略名称
    deck_seed: 随机数种子，用于重现洗牌结果，默认不固定
    max_rounds: 最大模拟局数
    parameters: 策略参数
    
    注意：模拟会在以下两种情况之一时结束：
    1. 剩余牌数小于2副牌（即LOW_CARDS_THRESHOLD = 104张）
    2. 达到最大局数max_rounds
    通常情况下，模拟会因为牌不足而提前结束，而不是达到max_rounds。
    因此实际模拟的局数通常小于max_rounds参数指定的值。
    parameters参数说明：
    observation_rounds: 观察期，默认6局
    strategy_table_id: 策略表ID
    """
    # 初始化参数
    parameters = parameters or {}
    print(f"参数: {parameters}")
    observation_rounds = parameters.get('observation_rounds', 6)  # 默认观望6局
    
    # 前端用户设置使用哪一种下注金额策略的id，需要到数据库中读取这个策略表的strategy_content
    strategy_table_id = parameters.get('strategy_table_id')
    if not strategy_table_id:
        print("错误：未提供strategy_table_id，无法继续模拟")
        return None
        
    # 获取策略表
    try:
        from models import BetStrategyTable
        strategy_table = BetStrategyTable.get_by_id(strategy_table_id)
        if not strategy_table:
            print(f"错误：未找到ID为{strategy_table_id}的策略表")
            return None
            
        strategy_content = strategy_table.strategy_content
        print(f"策略表ID: {strategy_table_id}, 策略内容: {strategy_content}")
        
        # 解析策略表, 返回table_data, 格式为[{条件字符串: 下注金额}, {条件字符串: 下注金额}, ...]
        table_data = BetStrategyTable.parse_strategy_text(strategy_content)
        if not table_data:
            print("错误：策略内容解析失败，可能格式不正确")
            return None
    except Exception as e:
        import traceback
        print(f"获取策略表失败: {str(e)}")
        traceback.print_exc()
        return None

    # 初始化洗牌
    deck, used_seed = shuffle_new_deck(fixed_seed=deck_seed)
    
    # 保存初始牌组，用于验证
    original_deck = deck.copy()
    
    # 存储每局结果和总统计
    rounds_data = []
    total_profit = 0
    win_rounds = 0
    lose_rounds = 0
    
    # 记录开始时间
    start_time = get_timestamp()
    
    # 创建模拟记录
    simulation_id = None
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor()
        
        # 保存模拟基本信息
        parameters_json = json.dumps(parameters, ensure_ascii=False)
        cursor.execute('''
            INSERT INTO simulations (
                timestamp, strategy_name, total_rounds, win_rounds, lose_rounds, 
                net_profit, deck_seed, parameters, main_choice
            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
            RETURNING id
        ''', (
            start_time,
            strategy_name,
            0,  # 初始设置为0，后面会更新
            0, 0, 0,
            str(used_seed),
            parameters_json,
            None
        ))
        
        # 获取模拟ID
        simulation_id = cursor.fetchone()[0]
        conn.commit()
        
        # 保存初始牌组状态
        save_deck_to_db(original_deck, used_seed, simulation_id)
        
        cursor.close()
        conn.close()
        
    except Exception as e:
        import traceback
        print(f"创建模拟记录错误: {str(e)}")
        traceback.print_exc()
        # 把参数 parameters 打印出来，看看调试
        print(f"参数: {parameters}")
        return None
    
    if not simulation_id:
        print("错误：创建模拟记录失败，未获取到simulation_id")
        return None
    
    # 主打方向（由观察期结束后确定）
    main_choice = None
    cards_dealt_count = 0   # 发牌数量
    
    # 记录输赢历史，用于下注金额策略，记录为['+1000', '-1000', '+1100','0',...],0表示和局或者没下注，+1000表示赢1000，-1000表示输1000
    win_loss_results = []
    
    # 开始模拟
    for round_id in range(1, max_rounds + 1):
        print(f"第{round_id}局")
        # 关键条件：如果牌不足2副，则结束模拟
        if len(deck) < LOW_CARDS_THRESHOLD:
            print(f"剩余牌数{len(deck)}张，不足{LOW_CARDS_THRESHOLD}张(2副牌)，模拟结束。")
            break
        
        # 是否在观察期内
        is_observation_mode = round_id <= observation_rounds
        
        # 如果处于观察期且尚未确定主打方向，尝试确定主打方向
        if is_observation_mode and main_choice is None and len(rounds_data) > 0:
            # 检查历史数据，找出第一个非和局结果作为主打方向
            for result in rounds_data:
                if result != 'tie':
                    main_choice = result
                    print(f"确定主打方向: {main_choice} (在观察期内)")
                    break
        
        # 根据策略确定下注方向（观察期内不下注）
        bet_choice = None if is_observation_mode else determine_bet_by_strategy(rounds_data, main_choice)
                
        # 确定下注金额，改成使用具体的策略表了
        bet_amount = determine_bet_amount_by_strategy(
            win_loss_results, table_data) if bet_choice else 0
        print(f"bet_amount: {bet_amount}")
        
        # 进行一局游戏
        game_result = play_single_round(deck, bet_choice, bet_amount, cards_dealt_count, main_choice)
        
        # 检查是否出错
        if 'error' in game_result:
            print(f"模拟中止，错误: {game_result['error']}")
            break
        
        # 更新发牌数量
        cards_dealt_count = game_result['cards_dealt_count']
        
        # 记录结果
        rounds_data.append(game_result['result'])
        
        # 确保主打方向在观察期结束时已确定
        if round_id == observation_rounds and main_choice is None:
            # 如果观察期结束仍未确定主打方向，再次尝试从历史中寻找
            for result in rounds_data:
                if result != 'tie':
                    main_choice = result
                    print(f"观察期结束，确定主打方向: {main_choice}")
                    break
            
            # 如果仍无法确定，打印警告
            if main_choice is None:
                print("警告: 观察期结束但无法确定主打方向，可能全是和局")
        
        # 更新当前局的主打方向
        game_result['main_choice'] = main_choice
        
        # 更新输赢统计（仅计算实际下注的局）
        if bet_choice:
            old_win_loss = win_loss_results.copy() if win_loss_results else []
            
            if game_result['win'] == True:  # 使用明确的True比较，避免与2(和局退钱)混淆
                win_rounds += 1
                total_profit += game_result['payout']
                # 记录为字符串，避免与0混淆,'+1000'表示赢1000，'-1000'表示输1000
                win_loss_str = f"+{bet_amount}" if game_result['payout'] > 0 else f"-{bet_amount}"
                win_loss_results.append(win_loss_str)  # 赢记为True
            elif game_result['win'] == False:
                lose_rounds += 1
                total_profit -= bet_amount
                # 记录为字符串，避免与0混淆,'-1000'表示输1000
                win_loss_str = f"-{bet_amount}"
                win_loss_results.append(win_loss_str)  # 输记为False
            elif game_result['win'] == 2:  # 和局退回本金的情况
                # 对于下注策略来说，和局应被视为"中性"结果，不改变下注金额
                # 使用特殊值None表示"中性"（不是赢也不是输）
                win_loss_str = "0"
                win_loss_results.append(win_loss_str)            
        else:
            old_win_loss = win_loss_results.copy() if win_loss_results else []
            # 未下注情况下添加"0"到输赢历史，保持历史记录连贯
            win_loss_str = "0"
            win_loss_results.append(win_loss_str)
        
        # 生成策略备注
        strategy_note = ""
        if is_observation_mode:
            strategy_note = "观望模式，不下注"
            if main_choice:
                strategy_note += f"，主打方向: {main_choice}"
        elif main_choice:
            # 计算和最新结果相同的连续次数
            latest_result = None
            consecutive_same = 0
            
            # 查找最近的非和局结果
            for result in reversed(rounds_data[:-1]):  # 不包括当前局
                if result != 'tie':
                    if latest_result is None:  # 第一次找到非和局结果
                        latest_result = result
                        consecutive_same = 1
                    elif result == latest_result:  # 与前一个结果相同
                        consecutive_same += 1
                    else:  # 与前一个结果不同，中断连续计数
                        break
            
            strategy_note = f"主打: {main_choice}, "
            
            if bet_choice is None:
                strategy_note += "四连看，本局不下注"
            elif bet_choice == main_choice:
                strategy_note += "常规跟主打"
            elif bet_choice != main_choice:
                strategy_note += f"反打{bet_choice}"
            
            if latest_result and consecutive_same > 1:
                strategy_note += f", 连续{consecutive_same}局{latest_result}"
        
        # 保存本局结果
        save_round_to_db(game_result, round_id, strategy_note, simulation_id)
    
    # 更新模拟总结果
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor()
        
        cursor.execute('''
            UPDATE simulations SET
            total_rounds = %s, win_rounds = %s, lose_rounds = %s, net_profit = %s, main_choice = %s
            WHERE id = %s
        ''', (
            len(rounds_data),
            win_rounds,
            lose_rounds,
            total_profit,
            main_choice,
            simulation_id
        ))
        
        conn.commit()
        cursor.close()
        conn.close()
        
    except Exception as e:
        print(f"更新模拟结果错误: {str(e)}")
    
    print(f"模拟完成，共进行{len(rounds_data)}局，剩余{len(deck)}张牌")
    
    # 返回模拟结果摘要
    return {
        'simulation_id': simulation_id,
        'strategy_name': strategy_name,
        'total_rounds': len(rounds_data),
        'win_rounds': win_rounds,
        'lose_rounds': lose_rounds,
        'pass_rounds': len(rounds_data) - win_rounds - lose_rounds,
        'win_rate': win_rounds / (win_rounds + lose_rounds) if (win_rounds + lose_rounds) > 0 else 0,
        'net_profit': total_profit,
        'deck_seed': used_seed,
        'main_choice': main_choice,
        'remaining_cards': len(deck)
    }

def get_simulation_results(simulation_id):
    """获取指定模拟的结果"""
    try:
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor(cursor_factory=RealDictCursor)
        
        # 获取模拟摘要
        cursor.execute('''
            SELECT * FROM simulations WHERE id = %s
        ''', (simulation_id,))
        
        summary = cursor.fetchone()
        
        if not summary:
            return None
        
        # 获取模拟详细记录
        cursor.execute('''
            SELECT * FROM simulation_rounds 
            WHERE simulation_id = %s
            ORDER BY round_id ASC
        ''', (simulation_id,))
        
        rounds = cursor.fetchall()
        
        # 解析JSON字段
        for row in rounds:
            if row['player_hand']:
                row['player_hand'] = json.loads(row['player_hand'])
            if row['banker_hand']:
                row['banker_hand'] = json.loads(row['banker_hand'])
        
        # 获取牌组信息
        cursor.execute('''
            SELECT * FROM decks WHERE simulation_id = %s
        ''', (simulation_id,))
        
        deck_info = cursor.fetchone()
        if deck_info and deck_info['deck_data']:
            deck_info['deck_data'] = json.loads(deck_info['deck_data'])
        
        return {
            'summary': summary,
            'rounds': rounds,
            'deck_info': deck_info
        }
    except Exception as e:
        print(f"Error fetching simulation results: {str(e)}")
        return None
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def get_statistics():
    """获取全部历史统计数据
    
    返回:
        总盈利、输得轮次，赢的轮次，主打庄的盈利数，主打庄的输的总数，
        主打闲的盈利数，主打闲的输的总数
    """
    conn = None
    cursor = None
    try:
        # 连接数据库
        conn = psycopg2.connect(**DB_CONFIG)
        cursor = conn.cursor(cursor_factory=RealDictCursor)
        
        print("正在查询数据库表以获取统计数据...")
        
        # 首先检查simulations表中是否有数据
        cursor.execute('SELECT COUNT(*) as count FROM simulations')
        simulations_count = cursor.fetchone()["count"]
        print(f"simulations表中有 {simulations_count} 条记录")
        
        # 如果simulations表有数据，直接使用该表进行统计
        if simulations_count > 0:
            print("从simulations表获取总体统计数据...")
            
            # 获取总体统计
            cursor.execute('''
                SELECT 
                    SUM(total_rounds) as total_rounds,
                    SUM(win_rounds) as win_rounds,
                    SUM(lose_rounds) as lose_rounds,
                    (SUM(total_rounds) - SUM(win_rounds) - SUM(lose_rounds)) as tie_rounds,
                    SUM(net_profit) as total_profit
                FROM simulations
            ''')
            
            overall_stats = cursor.fetchone()
            
            # 按主打方向统计
            cursor.execute('''
                SELECT 
                    main_choice,
                    SUM(total_rounds) as total_bets,
                    SUM(win_rounds) as win_rounds,
                    SUM(lose_rounds) as lose_rounds,
                    SUM(net_profit) as profit
                FROM simulations
                WHERE main_choice IS NOT NULL
                GROUP BY main_choice
            ''')
            
            main_choice_stats = cursor.fetchall()
            
            # 整理数据
            stats = {
                "overall": {
                    "total_rounds": overall_stats["total_rounds"] or 0,
                    "win_rounds": overall_stats["win_rounds"] or 0,
                    "lose_rounds": overall_stats["lose_rounds"] or 0,
                    "tie_rounds": overall_stats["tie_rounds"] or 0,
                    "total_profit": overall_stats["total_profit"] or 0
                },
                "by_bet_choice": {},  # 没有按下注方向的统计，因为simulations表没有这个信息
                "by_main_choice": {},
                "result_distribution": {},
                "recent_results": []
            }
            
            # 格式化按主打方向的统计
            for choice in main_choice_stats:
                stats["by_main_choice"][choice["main_choice"]] = {
                    "total_bets": choice["total_bets"] or 0,
                    "win_rounds": choice["win_rounds"] or 0,
                    "lose_rounds": choice["lose_rounds"] or 0,
                    "profit": choice["profit"] or 0
                }
            
            # 获取所有主打方向的盈亏情况
            print("根据主打方向估算结果分布...")
            banker_wins = 0
            player_wins = 0
            tie_rounds = overall_stats["tie_rounds"] or 0
            
            # 根据主打方向统计数据估算结果分布
            for choice, stats_data in stats["by_main_choice"].items():
                if choice == "banker":
                    banker_wins += stats_data["win_rounds"]
                    player_wins += stats_data["lose_rounds"]
                elif choice == "player":
                    player_wins += stats_data["win_rounds"]
                    banker_wins += stats_data["lose_rounds"]
            
            # 填充结果分布数据
            stats["result_distribution"] = {
                "banker": banker_wins,
                "player": player_wins,
                "tie": tie_rounds
            }
            
            # 获取最近20个模拟的主打方向作为最近走势
            cursor.execute('''
                SELECT result, main_choice 
                FROM (
                    SELECT 
                        CASE 
                            WHEN win_rounds > lose_rounds THEN '胜利'
                            ELSE '失败'
                        END as result,
                        main_choice,
                        id
                    FROM simulations
                    ORDER BY id DESC
                    LIMIT 20
                ) as recent
            ''')
            
            recent_results_data = cursor.fetchall()
            
            # 根据每个模拟的主打方向和输赢情况，推测最可能的结果
            stats["recent_results"] = []
            for item in recent_results_data:
                main_choice = item["main_choice"]
                result = item["result"]
                
                if main_choice == "banker":
                    if result == "胜利":
                        stats["recent_results"].append("banker")
                    else:
                        stats["recent_results"].append("player")
                elif main_choice == "player":
                    if result == "胜利":
                        stats["recent_results"].append("player")
                    else:
                        stats["recent_results"].append("banker")
                else:
                    # 如果主打方向为空，随机添加
                    stats["recent_results"].append("banker")
            
            print(f"从simulations表成功获取统计数据，总局数: {overall_stats['total_rounds']}")
            return stats
            
        # 检查rounds表是否有数据
        cursor.execute('SELECT COUNT(*) as count FROM rounds')
        rounds_count = cursor.fetchone()["count"]
        print(f"rounds表中有 {rounds_count} 条记录")
        
        # 如果rounds表有数据，使用常规查询
        if rounds_count > 0:
            print("使用rounds表数据进行统计...")
            
            # 总体统计
            cursor.execute('''
                SELECT 
                    COUNT(*) as total_rounds,
                    SUM(CASE WHEN win_or_lose = 1 THEN 1 ELSE 0 END) as win_rounds,
                    SUM(CASE WHEN win_or_lose = 0 THEN 1 ELSE 0 END) as lose_rounds,
                    SUM(CASE WHEN win_or_lose = 2 THEN 1 ELSE 0 END) as tie_rounds,
                    SUM(payout) as total_profit
                FROM rounds
            ''')
            
            overall_stats = cursor.fetchone()
            
            # 按下注方向统计
            cursor.execute('''
                SELECT 
                    bet_choice,
                    COUNT(*) as total_bets,
                    SUM(CASE WHEN win_or_lose = 1 THEN 1 ELSE 0 END) as win_rounds,
                    SUM(CASE WHEN win_or_lose = 0 THEN 1 ELSE 0 END) as lose_rounds,
                    SUM(payout) as profit
                FROM rounds
                WHERE bet_choice IN ('banker', 'player')
                GROUP BY bet_choice
            ''')
            
            choice_stats = cursor.fetchall()
            
            # 主打方向统计
            cursor.execute('''
                SELECT 
                    main_choice,
                    COUNT(*) as total_bets,
                    SUM(CASE WHEN win_or_lose = 1 THEN 1 ELSE 0 END) as win_rounds,
                    SUM(CASE WHEN win_or_lose = 0 THEN 1 ELSE 0 END) as lose_rounds,
                    SUM(payout) as profit
                FROM rounds
                WHERE main_choice IS NOT NULL
                GROUP BY main_choice
            ''')
            
            main_choice_stats = cursor.fetchall()
            
            # 整理统计数据
            stats = {
                "overall": overall_stats,
                "by_bet_choice": {},
                "by_main_choice": {}
            }
            
            # 格式化按下注方向的统计
            for choice in choice_stats:
                stats["by_bet_choice"][choice["bet_choice"]] = {
                    "total_bets": choice["total_bets"],
                    "win_rounds": choice["win_rounds"] or 0,  # 防止None值
                    "lose_rounds": choice["lose_rounds"] or 0,
                    "profit": choice["profit"] or 0
                }
            
            # 格式化按主打方向的统计  
            for choice in main_choice_stats:
                stats["by_main_choice"][choice["main_choice"]] = {
                    "total_bets": choice["total_bets"],
                    "win_rounds": choice["win_rounds"] or 0,
                    "lose_rounds": choice["lose_rounds"] or 0,
                    "profit": choice["profit"] or 0
                }
            
            # 获取所有结果的输赢分布（用于图表展示）
            cursor.execute('''
                SELECT 
                    result,
                    COUNT(*) as count
                FROM rounds
                GROUP BY result
            ''')
            
            result_distribution = cursor.fetchall()
            stats["result_distribution"] = {}
            
            for result in result_distribution:
                stats["result_distribution"][result["result"]] = result["count"]
            
            # 计算最近20局庄闲和的分布（用于趋势展示）
            cursor.execute('''
                SELECT result
                FROM rounds
                ORDER BY id DESC
                LIMIT 20
            ''')
            
            recent_results = cursor.fetchall()
            stats["recent_results"] = [row["result"] for row in recent_results]
            
            print("成功获取统计数据，总局数:", overall_stats["total_rounds"])
            return stats
            
        # 检查simulation_rounds表是否有数据
        cursor.execute('SELECT COUNT(*) as count FROM simulation_rounds')
        simulation_rounds_count = cursor.fetchone()["count"]
        print(f"simulation_rounds表中有 {simulation_rounds_count} 条记录")
        
        # 如果simulation_rounds表有数据，使用该表进行统计
        if simulation_rounds_count > 0:
            print("使用simulation_rounds表数据进行统计...")
            
            # 总体统计
            cursor.execute('''
                SELECT 
                    COUNT(*) as total_rounds,
                    SUM(CASE WHEN win_or_lose = 1 THEN 1 ELSE 0 END) as win_rounds,
                    SUM(CASE WHEN win_or_lose = 0 THEN 1 ELSE 0 END) as lose_rounds,
                    SUM(CASE WHEN win_or_lose = 2 THEN 1 ELSE 0 END) as tie_rounds,
                    SUM(payout) as total_profit
                FROM simulation_rounds
            ''')
            
            overall_stats = cursor.fetchone()
            
            # 按下注方向统计
            cursor.execute('''
                SELECT 
                    bet_choice,
                    COUNT(*) as total_bets,
                    SUM(CASE WHEN win_or_lose = 1 THEN 1 ELSE 0 END) as win_rounds,
                    SUM(CASE WHEN win_or_lose = 0 THEN 1 ELSE 0 END) as lose_rounds,
                    SUM(payout) as profit
                FROM simulation_rounds
                WHERE bet_choice IN ('banker', 'player')
                GROUP BY bet_choice
            ''')
            
            choice_stats = cursor.fetchall()
            
            # 主打方向统计
            cursor.execute('''
                SELECT 
                    main_choice,
                    COUNT(*) as total_bets,
                    SUM(CASE WHEN win_or_lose = 1 THEN 1 ELSE 0 END) as win_rounds,
                    SUM(CASE WHEN win_or_lose = 0 THEN 1 ELSE 0 END) as lose_rounds,
                    SUM(payout) as profit
                FROM simulation_rounds
                WHERE main_choice IS NOT NULL
                GROUP BY main_choice
            ''')
            
            main_choice_stats = cursor.fetchall()
            
            # 整理统计数据
            stats = {
                "overall": overall_stats,
                "by_bet_choice": {},
                "by_main_choice": {}
            }
            
            # 格式化按下注方向的统计
            for choice in choice_stats:
                stats["by_bet_choice"][choice["bet_choice"]] = {
                    "total_bets": choice["total_bets"],
                    "win_rounds": choice["win_rounds"] or 0,
                    "lose_rounds": choice["lose_rounds"] or 0,
                    "profit": choice["profit"] or 0
                }
            
            # 格式化按主打方向的统计  
            for choice in main_choice_stats:
                stats["by_main_choice"][choice["main_choice"]] = {
                    "total_bets": choice["total_bets"],
                    "win_rounds": choice["win_rounds"] or 0,
                    "lose_rounds": choice["lose_rounds"] or 0,
                    "profit": choice["profit"] or 0
                }
            
            # 获取所有结果的输赢分布（用于图表展示）
            cursor.execute('''
                SELECT 
                    result,
                    COUNT(*) as count
                FROM simulation_rounds
                GROUP BY result
            ''')
            
            result_distribution = cursor.fetchall()
            stats["result_distribution"] = {}
            
            for result in result_distribution:
                stats["result_distribution"][result["result"]] = result["count"]
            
            # 计算最近20局庄闲和的分布（用于趋势展示）
            cursor.execute('''
                SELECT result
                FROM simulation_rounds
                ORDER BY id DESC
                LIMIT 20
            ''')
            
            recent_results = cursor.fetchall()
            stats["recent_results"] = [row["result"] for row in recent_results]
            
            print(f"从simulation_rounds表成功获取统计数据，总局数: {overall_stats['total_rounds']}")
            return stats
            
        # 所有表都没有数据，返回模拟数据
        print("数据库中没有实际数据，返回模拟统计数据供前端显示")
        mock_data = {
            "overall": {
                "total_rounds": 1000,
                "win_rounds": 450, 
                "lose_rounds": 480,
                "tie_rounds": 70,
                "total_profit": 12500
            },
            "by_bet_choice": {
                "banker": {
                    "total_bets": 680,
                    "win_rounds": 350,
                    "lose_rounds": 330,
                    "profit": 16800
                },
                "player": {
                    "total_bets": 320,
                    "win_rounds": 100,
                    "lose_rounds": 150,
                    "profit": -4300
                }
            },
            "by_main_choice": {
                "banker": {
                    "total_bets": 570,
                    "win_rounds": 310,
                    "lose_rounds": 260,
                    "profit": 14500
                },
                "player": {
                    "total_bets": 280,
                    "win_rounds": 85,
                    "lose_rounds": 195,
                    "profit": -2000
                }
            },
            "result_distribution": {
                "banker": 520,
                "player": 410,
                "tie": 70
            },
            "recent_results": [
                "banker", "player", "banker", "banker", "player", 
                "tie", "banker", "player", "banker", "banker",
                "player", "banker", "player", "banker", "tie",
                "player", "banker", "banker", "player", "banker"
            ]
        }
        return mock_data
    except psycopg2.Error as db_err:
        print(f"数据库错误: {str(db_err)}")
        return None
    except Exception as e:
        print(f"获取统计数据时发生错误: {str(e)}")
        return None
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()

def determine_bet_by_strategy_table(previous_win_amounts, strategy_table=None):
    """
    根据下注策略表和历史输赢金额记录确定下一局的下注金额
    
    策略表格式：[[历史记录数组], 下注金额]
    例如: [['-1000'], 1100] 表示如果最近输1000，则下注1100
    
    Args:
        previous_win_amounts: 之前几局的输赢金额列表，例如[1000, -1000, 1100]
                             正数表示赢，负数表示输，0表示和局或未下注
        strategy_table: 策略表，如果为None则使用数据库中的默认策略表
    
    Returns:
        下一局的下注金额，如果没有匹配的策略则返回None
    """
    from models import BetStrategyTable
    import json
    
    # 如果没有提供策略表，则获取默认策略表
    if strategy_table is None:
        strategy_obj = BetStrategyTable.get_default()
        if not strategy_obj:
            print("警告：未找到默认下注策略表，使用配置文件中的策略表")
            # 使用配置文件中的默认策略表
            from config import BET_STRATEGY_TABLE
            strategy_table = BET_STRATEGY_TABLE
        else:
            strategy_table = strategy_obj.get_table_data()
    
    # 如果没有历史记录，使用配置的初始值（默认为1000）
    if not previous_win_amounts:
        # 查找策略表中的默认初始下注额
        for rule in strategy_table:
            if len(rule[0]) == 0:  # 空条件，即初始下注
                return rule[1]
        # 如果没有定义初始下注额，则返回默认值1000
        return 1000
    
    # 将历史输赢金额转换为策略中使用的格式
    history_str = []
    for amount in previous_win_amounts:
        if amount > 0:
            history_str.append(f"+{amount}")  # 赢了加上加号
        else:
            history_str.append(f"{amount}")   # 输了本身就有负号
            
    # 从最近的历史开始检查，尝试找到匹配的策略
    for i in range(len(history_str), 0, -1):
        # 检查最近的i个记录是否有匹配的规则
        recent_history = history_str[-i:]
        
        # 遍历策略规则，寻找匹配的条件
        for rule in strategy_table:
            conditions = rule[0]
            bet_amount = rule[1]
            
            # 检查是否有匹配的规则
            
            # 1. 检查单个条件匹配（如 -1000:1100）
            if len(conditions) == 1 and len(recent_history) >= 1:
                if conditions[0] == recent_history[-1]:
                    print(f"匹配单个条件规则: {conditions[0]} -> 下注 {bet_amount}")
                    return bet_amount
            
            # 2. 检查多条件"或"匹配（如 +1000/+2000/+3000:1000）
            if '/' in conditions[0]:
                or_conditions = conditions[0].split('/')
                if recent_history[-1] in or_conditions:
                    print(f"匹配'或'条件规则: {or_conditions} -> 下注 {bet_amount}")
                    return bet_amount
            
            # 3. 检查连续条件匹配（如 +1000,+1000,+1000:2000）
            if ',' in conditions[0]:
                seq_conditions = conditions[0].split(',')
                if len(recent_history) >= len(seq_conditions):
                    match = True
                    for j in range(len(seq_conditions)):
                        if seq_conditions[j] != recent_history[-(len(seq_conditions)-j)]:
                            match = False
                            break
                    if match:
                        print(f"匹配连续条件规则: {seq_conditions} -> 下注 {bet_amount}")
                        return bet_amount
            
            # 4. 检查完全匹配（旧格式兼容）
            if isinstance(conditions, list) and len(conditions) == len(recent_history):
                match = True
                for j in range(len(conditions)):
                    if conditions[j] != recent_history[j]:
                        match = False
                        break
                
                if match:
                    print(f"匹配完全匹配规则: {conditions} -> 下注 {bet_amount}")
                    return bet_amount
    
    # 如果没有找到匹配的规则，尝试使用默认值
    default_amount = None
    for rule in strategy_table:
        if len(rule[0]) == 0 or (len(rule[0]) == 1 and rule[0][0] == ''):
            default_amount = rule[1]
            break
            
    if default_amount:
        return default_amount
        
    # 如果仍然没有找到默认值，返回1000
    return 1000

# 如果是直接运行此文件，则执行测试
if __name__ == "__main__":
    # 添加命令行参数支持
    import argparse
    parser = argparse.ArgumentParser(description='测试百家乐策略和下注金额计算')
    parser.add_argument('--test', action='store_true', help='运行下注金额计算测试')
    parser.add_argument('--test-strategy-table', action='store_true', help='运行下注策略表测试')
    args = parser.parse_args()
    